home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / pctj8401.arc / DUMBTERM.ASM < prev    next >
Assembly Source File  |  1984-01-30  |  15KB  |  627 lines

  1. ;------------------------------------------------------------------
  2. ;                     DUMBTERM
  3. ; Author:    CJ Dunford
  4. ; Rev.:        09/12/83
  5. ; Source:    DUMBTERM.ASM
  6. ; Object:    DUMBTERM.OBJ
  7. ; Code:        DUMBTERM.EXE
  8. ; O/S:        PCDOS 1.1, 2.0
  9. ;
  10. ; Note that the program assumes that the RS232 port is configured
  11. ; as COM1.  It will have to be modified to use COM2.  Also,
  12. ; the communications parameters are set as 300 baud, 7 data bits,
  13. ; 1 stop bit, even parity.  This can be changed--see the INIT
  14. ; procedure.  DUMBTERM will easily keep up with 1200 baud or more.
  15. ;
  16. ; Assembly/link:
  17. ;   Assemble: MASM dumbterm;
  18. ;   Link:     LINK dumbterm;
  19. ;
  20. ; Execution:
  21. ;   (from DOS prompt): DUMBTERM
  22. ;------------------------------------------------------------------
  23.  
  24. ; * * * * * * * * * * * * * * *
  25. ;   EQUATES & DEFINITIONS
  26. ; * * * * * * * * * * * * * * *
  27.  
  28. ; ----- Define size of buffer
  29. BUFSIZE        equ    4096        ; 4K--can be adjusted
  30.  
  31. ; ----- ASCII codes
  32. LF        equ    0AH        ; Line feed
  33. CR        equ    0DH        ; Carriage return
  34. ESC        equ    1BH        ; Escape
  35.  
  36. ; ----- BIOS calls
  37. RS232           equ    14H        ; RS232 service
  38. kbd_io           equ    16H        ; Keyboard service
  39.  
  40. ; ----- INS8250 ACE registers
  41.  
  42. THR    equ    3F8H        ; Trans    holding    register (write)
  43. RBR    equ    3F8H        ; Receiver buffer register (read)
  44. IER    equ    3F9H        ; Interrupt enable register
  45. LCR    equ    3FBH        ; Line control register.
  46.                 ; Bit 7    of LCR is "DLAB".  DLAB    must
  47.                 ; be zero to access THR, RBR, IER.
  48. MCR    equ    3FCH        ; Modem    control    register
  49. LSR    equ    3FDH        ; Line status register
  50. MSR    equ    3FEH        ; Modem    status register
  51.  
  52.  
  53. ; ----- Comm parameter definition
  54. ; Refer    to IBM Tech Ref, page A-20
  55. ; See proc INIT    for usage
  56.  
  57. commparm record    baud:3,    parity:2, stopbits:1, wordbits:2
  58.  
  59. ; Baud rates
  60. B110        equ    000B
  61. B150        equ    001B
  62. B300        equ    010B
  63. B600        equ    011B
  64. B1200        equ    100B
  65. B2400        equ    101B
  66. B4800        equ    110B
  67. B9600        equ    111B
  68.  
  69. ; Parity
  70. no_parity    equ    00B
  71. odd_parity    equ    01B
  72. even_parity    equ    11B
  73.  
  74. ; Stop bits
  75. stop1        equ    0
  76. stop2        equ    1
  77.  
  78. ; Data bits
  79. data7        equ    10B
  80. data8        equ    11B
  81.  
  82.  
  83. ; * * * * * * * * * * * * * * *
  84. ;    MACROS
  85. ; * * * * * * * * * * * * * * *
  86.  
  87. @bioscall MACRO    call_num, parm
  88. ;; Generates an 'INT call_num', with parm in AH
  89.     IFNB <parm>
  90.       mov ah,parm
  91.     ENDIF
  92.     int call_num
  93.     ENDM
  94.  
  95.  
  96. @doscall MACRO function,parm
  97. ;; Generates a DOS function call with parm in AL
  98.     IFNB <parm>
  99.      mov al,parm
  100.     ENDIF
  101.     @bioscall 21H,function
  102.     endm
  103.  
  104.  
  105. ; * * * * * * * * * * * * * *
  106. ;    DATA & STACK SEGMENTS
  107. ; * * * * * * * * * * * * * *
  108.  
  109. data segment para public 'data'
  110.  
  111. ; ----- The string section
  112. sgreeting    db    '--- ONLINE ---',CR,LF,'$'
  113. sgoodbye    db    CR,LF,'--- OFFLINE ---',CR,LF,'$'
  114. serr1        db    '<R>$'    ; RS232    receive    error
  115. serr2        db    '<S>$'    ; RS232    send error
  116. serr3        db    '<B>$'    ; Receive buffer overflow error
  117.  
  118. ; ----- Flags
  119. brcv_err    db    0    ; Nonzero on RS232 receive error
  120. boverflow    db    0    ; Nonzero on buffer overflow
  121. bdoneflag    db    0    ; Nonzero after ESC from kbd
  122.  
  123. ; ----- Received data buffer and associated pointers
  124. ; >> Buffer is empty if head pointer = tail pointer
  125. wbufhead    dw    buffer    ; Pointer to head of buffer
  126. wbuftail    dw    buffer     ; Pointer to tail of buffer
  127. buffer        db    BUFSIZE dup (?)
  128. bufend        equ $
  129. data ends
  130.  
  131. ; ----- Stack
  132. stack segment para stack 'stack'
  133.     db    256 dup (?)
  134. stack ends
  135.  
  136.  
  137. ; * * * * * * * * * * * * *
  138. ;     PROGRAM MAINLINE
  139. ; * * * * * * * * * * * * *
  140.  
  141. code    segment    para public 'code'
  142.     assume cs:code, ds:data, ss:stack
  143.  
  144. main    proc far
  145.  
  146. ; ----- Initialize
  147.     push ds            ; Set up long ret to DOS
  148.     sub ax,ax
  149.     push ax
  150.     call init        ; Rest of initialization
  151.  
  152. ; ----- Main program loop
  153. M100:
  154.     call buffer_check       ; Check RS232 bfr. Display if not empty
  155.     call kb_check           ; Check kbd. Send to RS232.
  156.     test bdoneflag,0FFH    ; Non-zero if done
  157.     jz M100            ; Loop till ESC received
  158.  
  159. ; ----- ESC received.  Clean up interrupt & exit
  160.     call cleanup        ; Clean    up
  161.     ret            ; Return to DOS
  162. main    endp
  163.  
  164.  
  165. ; * * * * * * * * * * * * * * *
  166. ;     PRIMARY BLOCKS
  167. ; * * * * * * * * * * * * * * *
  168.  
  169. ; -----    INIT ------------------------------
  170. ; Program initialization:
  171. ;   -- Set up RS232
  172. ;   -- Set up vector for RS232 interrupt (INT 0CH)
  173. ;   -- Enable IRQ4
  174. ;   -- Enable RS232 interrupt on data ready
  175. ;
  176. ; NOTE: The communications parameters are established
  177. ; here.  To use other parameters, change the parameters
  178. ; in the 'mov al,commparm' statement below.  See the
  179. ; communications parameters record definition (above)
  180. ; for the correct abbreviations.
  181. ;
  182. ; Examples:
  183. ;   1200,N,8,1:    mov al,commparm <B1200,no_parity,stop1,data8>
  184. ;   4800,O,7,2: mov al,commparm <B4800,odd_parity,stop2,data7>
  185. ; -----------------------------------------
  186.  
  187. init proc near
  188.  
  189. ; ----- Initialize RS232: 300,8,N,1
  190.     mov dx,0            ; COM1
  191.     mov al,commparm    <B300,no_parity,stop1,data8>
  192.     @bioscall RS232,0
  193.  
  194. ; ----- Set up INT x'0C' for IRQ4
  195.     cli                ; Interrupts off during    setup
  196.     push ds                ; Save DS
  197.     mov dx,offset ISR        ; Point    to RS232 ISR in    DS:DX
  198.     push cs
  199.     pop ds
  200.     @doscall 25H,0CH        ; Set int vctr for IRQ4
  201.     pop ds                ; Restore DS
  202.  
  203. ; ----- Enable IRQ4 on 8259 interrupt controller
  204.     in al,21H            ; Get current masks
  205.     and al,11101111B        ; Reset    IRQ4 mask
  206.     out 21H,al            ; And restore to IMR
  207.  
  208. ; ----- Enable 8250 data ready interrupt
  209.     mov dx,LCR            ; DX ==> LCR
  210.     in al,dx                        ; Reset DLAB for IER access
  211.     and al,01111111B
  212.     out dx,al
  213.     mov dx,IER            ; Address IER
  214.     mov al,00000001B        ; Enable 'data-ready' interrupt
  215.     out dx,al
  216.  
  217. ; ----- Enable OUT2 on 8250
  218.     mov dx,MCR             ; Address MCR
  219.     mov al,00001000B        ; Enable OUT2
  220.     out dx,al
  221.     sti
  222.  
  223. ; ----- Display greeting & return
  224.     mov ax,data            ; Establish data seg address
  225.     mov ds,ax
  226.     mov dx,offset sgreeting        ; Point to greeting
  227.     call strdisp            ; Display it
  228.     ret
  229. init endp
  230.  
  231.  
  232. ; ---- BUFFER_CHECK -----------------------
  233. ; RS232 buffer check
  234. ;
  235. ; This block checks the received data buffer.
  236. ; It functions as follows:
  237. ;
  238. ; IF the RS232 input buffer is not empty
  239. ;    Get the first character
  240. ;    Display the character
  241. ;    Update buffer pointer
  242. ; IF the RS232 receive error flag is nonzero
  243. ;    Display an error indicator
  244. ; IF the buffer overflow flag is nonzero
  245. ;    Display an error indicator
  246. ;
  247. ; Entry:
  248. ;  No requirement
  249. ; Exit:
  250. ;  AX, BX, DX destroyed
  251. ; -----------------------------------------
  252.  
  253. buffer_check proc near
  254.  
  255. ; ----- Check buffer status
  256.     mov bx,wbufhead            ; Buffer head pointer
  257.     cmp bx,wbuftail            ; Buffer empty if head = tail
  258.     je BC100            ; Jump if empty
  259.  
  260. ; ----- Something in buffer--get 1st char, fix pointers
  261.     mov al,[bx]            ; Get the char
  262.     call incptr            ; Bump buffer head pointer
  263.     mov wbufhead,bx
  264.  
  265. ; ----- Display character received.  Filter CR/LF
  266.     cmp al,LF            ; Is it a line feed?
  267.     je BC100            ; Skip display if yes
  268.     call chdisp            ; Display if no
  269.     cmp al,CR            ; Is it a CR?
  270.     jne BC100             ; Jump if not
  271.     mov al,LF            ; Send LF if yes
  272.     call chdisp
  273.  
  274. ; ----- Test RS232 receive status; display errors
  275. BC100:
  276.     test brcv_err,0FFH        ; Flag nonzero if errors
  277.     jz BC200            ; Jump if no errors
  278.     mov dx,offset serr1        ; Point to error msg
  279.     call strdisp
  280.     mov brcv_err,0            ; Clear error flag
  281.  
  282. ; ----- Test for buffer overflow; display errors
  283. BC200:
  284.     test boverflow,0FFH
  285.     jz BC300            ; Z if no overflow
  286.     mov boverflow,0            ; Clear the flag
  287.     mov dx,offset serr3        ; Point to error msg
  288.     call strdisp            ; And display
  289.  
  290. BC300:
  291.     ret
  292. buffer_check endp
  293.  
  294. ; ----- KB_CHECK --------------------------
  295. ; Check keyboard.  Functions as follows:
  296. ;
  297. ; Check the keyboard status
  298. ; IF a character is available
  299. ;   IF the character is ESC
  300. ;      set the 'done' flag
  301. ;   ELSE
  302. ;      send it to RS232 and watch for errors
  303. ;
  304. ; Note that this routine does not echo the KB characters
  305. ; to the display.   Display occurs only when the characters
  306. ; are echoed back by the remote terminal.
  307. ;
  308. ; Entry:
  309. ;  No requirement
  310. ; Exit:
  311. ;  AX, DX destroyed
  312. ; -----------------------------------------
  313.  
  314. kb_check proc near
  315.  
  316. ; -----    Poll keyboard, check chars received
  317.     call kb_poll                    ; Poll the keyboard
  318.     jz KBC900            ; Kbd clear, exit
  319.     cmp al,ESC            ; Escape?
  320.     jne KBC100            ; No, continue
  321.     mov bdoneflag,0FFH        ; Yes, set termination flag
  322.     jmp short KBC900
  323.  
  324. ; ----- Send the received char, watch for errors
  325. KBC100:
  326.     call RS232_out            ; Send it
  327.     test ah,80H            ; Time out?
  328.     jz KBC900            ; No, sent OK
  329.     mov dx,offset serr2        ; Point to error msg
  330.     call strdisp            ; And display it
  331.  
  332. KBC900:
  333.     ret
  334. kb_check endp
  335.  
  336.  
  337. ; -----    ISR -------------------------------
  338. ; This is the RS232 interrupt service routine.  It
  339. ; is entered whenever the RS232 port interrupts on a
  340. ; 'data ready' condition.  The routine simply reads
  341. ; the data from the asynch chip and stuffs it in the
  342. ; buffer.  Note that the process of reading the
  343. ; received data register in the 8250 clears IRQ4.
  344. ; However, the 8259 must be told specifically that the
  345. ; interrupt service is complete.
  346. ;
  347. ; This replaces the function 2 of BIOS interrupt 14H
  348. ; (receive a character over the comm line).  Since
  349. ; it cannot return errors in a register, it puts the
  350. ; error marker in memory at 'brcv_err'.  The error
  351. ; flag is 'sticky'--a successful read will NOT clear a
  352. ; prior error indication.  This allows the program
  353. ; mainline to examine the error status at its
  354. ; leisure.  Error bits are the same as in RS232OUT,
  355. ; above, except that ONLY the error bits are set,
  356. ; and bit 7 is not used (always 0).  In other words,
  357. ; brcv_err is nonzero only on an error.  Timeout
  358. ; errors are not possible here.
  359. ;
  360. ; The ISR will set the overflow flag if the buffer
  361. ; should overflow.  Shouldn't happen.
  362. ; -----------------------------------------
  363.  
  364. ISR    proc near
  365.     sti            ; Allow    other interrupts
  366.     push ax            ; Save all regs used
  367.     push bx
  368.     push dx
  369.     push si
  370.     push ds
  371.  
  372. ; ----- Establish data addressability
  373.     mov ax,data
  374.     mov ds,ax
  375.  
  376. ; ----- Get error bits
  377.     mov dx,LSR        ; Base address of RS232
  378.     in al,dx        ; Get status
  379.     and al,00011110B    ; Mask non-error bits
  380.     jz ISR010        ; Skip error set if OK
  381.     mov brcv_err,al        ; Set error indicator
  382.  
  383. ; ----- Get incoming character and buffer it
  384. ISR010:
  385.     mov dx,RBR        ; Receiver buffer
  386.     in al,dx        ; Get input character
  387.     mov bx,wbuftail        ; Buffer input pointer
  388.     mov si,bx        ; Save pointer b4 increment
  389.     call incptr        ; Bump input pointer
  390.     cmp bx,wbufhead        ; Overflow if head = tail
  391.     je ISR020        ; Overflow
  392.     mov [si],al        ; No overflow, save char in buffer
  393.     mov wbuftail,bx        ; And new input    pointer
  394.     jmp short ISR999
  395. ISR020:
  396.     mov boverflow,0FFH    ; Set overflow flag
  397.  
  398. ; ----- Signal end of interrupt to 8259
  399. ISR999:
  400.     cli
  401.     mov al,20H        ; Non-specific EOI
  402.     out 20H,al        ; Send it
  403.  
  404. ; ----- Restore regs & return.  IRET reenables interrupts
  405.     pop ds
  406.     pop si
  407.     pop dx
  408.     pop bx
  409.     pop ax
  410.     iret
  411. ISR    endp
  412.  
  413.  
  414. ; ----- CLEANUP --------------------------
  415. ; End of program housekeeping
  416. ;   -- Disable IRQ4
  417. ;   -- Disable 8250 interrupts
  418. ;   -- Disable OUT2
  419. ;   -- Display offline message
  420. ; ----------------------------------------
  421.  
  422. cleanup    proc near
  423.  
  424. ; ----- Disable IRQ4 on 8259
  425.     cli
  426.     in al,21H            ; IMR
  427.     or al,00010000B            ; Mask bit 4--IRQ4
  428.     out 21H,al
  429.  
  430. ; ----- Disable 8250 data ready interrupt
  431.     mov dx,LCR            ; DX ==> LCR
  432.     in al,dx                        ; Reset DLAB for IER access
  433.     and al,01111111B
  434.     out dx,al
  435.     mov dx,IER            ; Address IER
  436.     mov al,0            ; Disable all 8250 interrupts
  437.     out dx,al
  438.  
  439. ; ----- Disable OUT2 on 8250
  440.     mov dx,MCR             ; Address MCR
  441.     mov al,0            ; Disable OUT2
  442.     out dx,al
  443.     sti
  444.  
  445. ; ----- Display bye-bye
  446.     mov dx,offset sgoodbye
  447.     call strdisp
  448.     ret
  449. cleanup    endp
  450.  
  451.  
  452. ; * * * * * * * * * * * * * * * *
  453. ;    I/O & GENERAL SUBROUTINES
  454. ; * * * * * * * * * * * * * * * *
  455.  
  456. ; -----    KB_POLL ---------------------------
  457. ; Set/reset Z flag on keyboard buffer status.
  458. ;
  459. ; Entry:
  460. ;  No requirements
  461. ; Exit:
  462. ;  Z = 1 if nothing available
  463. ;  Z = 0 if char available from kbd
  464. ;  IF Z = 0
  465. ;    AL = char
  466. ;    AH = scan code
  467. ; Other regs preserved
  468. ; -----------------------------------------
  469.  
  470. kb_poll proc near
  471.     @bioscall kbd_io,1    ; Poll KB. Sets    Z flag if KB bfr empty
  472.     jz KB999        ; Nothing there
  473.     pushf                   ; Save flag status
  474.     @bioscall kbd_io,0    ; Something there; get it
  475.     popf
  476. KB999:
  477.     ret
  478. kb_poll endp
  479.  
  480.  
  481.  
  482. ; --- RS232_out --------------------------
  483. ; RS232 output routine
  484. ;
  485. ; This routine sends one character to the RS232 port.
  486. ; It replaces function 1 of BIOS int 14H.  This is
  487. ; necessary because BIOS will disable the RS232
  488. ; interrupt (by disabling OUT2) every time it is
  489. ; called.
  490. ;
  491. ; Entry:
  492. ;  AL = character to be transmitted
  493. ; Exit:
  494. ;  AH = send status
  495. ;    Bit 7 = 1 if RS232 timeout occurred
  496. ;    IF bit 7 = 0
  497. ;       bit 6: trans shift register empty
  498. ;       bit 5: trans holding register empty
  499. ;       bit 4: break detect
  500. ;       bit 3: framing error
  501. ;       bit 2: parity error
  502. ;       bit 1: overrun error
  503. ;       bit 0: data ready
  504. ;  Other regs preserved
  505. ; ----------------------------------------
  506.  
  507. RS232_out proc near
  508.     push bx            ; Save regs used
  509.     push cx
  510.     push dx
  511.  
  512. ; ----- Set up RS232
  513.     mov bl,al        ; Save char to BL temporarily
  514.     mov dx,MCR        ; Modem    Control    Register
  515.     mov al,00001011B    ; OUT2,    DTR, RTS
  516.     out dx,al
  517.     sub cx,cx        ; Initialize timeout count
  518.     mov dx,MSR        ; Modem    Status Register
  519.  
  520. ; ----- Wait for DSR
  521. RS100:
  522.     in al,dx
  523.     test al,20H        ; Data set ready?
  524.     jnz RS150        ; Yes
  525.     loop RS100        ; No, retry till timeout
  526.     mov ah,80H        ; Set timeout
  527.     jmp short RSXIT        ; And quit
  528.  
  529. ; ----- Wait for CTS
  530. RS150:
  531.     sub cx,cx        ; Another timeout count
  532. RS200:
  533.     in al,dx
  534.     test al,10H        ; Clear    to send?
  535.     jnz RS250        ; Yes
  536.     loop RS200        ; No, loop till    timeout
  537.     mov ah,80H        ; Timeout, set flag
  538.     jmp short RSXIT        ; And quit
  539.  
  540. ; ----- Wait for THRE
  541. RS250:
  542.     mov dx,LSR        ; Line Status Register
  543.     sub cx,cx        ; Yet another timeout count
  544. RS300:
  545.     in al,dx        ; LSR status
  546.     test al,20H        ; Transmit holding reg empty?
  547.     jnz RS350        ; Yes
  548.     loop RS300        ; No, loop till    timeout
  549.     mov ah,80H        ; Timeout, set flag
  550.     jmp short RSXIT
  551.  
  552. ; ----- Get line status, send char
  553. RS350:
  554.     mov ah,al        ; Get line status for return
  555.     and ah,01111111B    ; Mask out bit 7
  556.     mov al,bl        ; Restore char to AL
  557.     mov dx,THR        ; Trasnmit holding register
  558.     out dx,al        ; Output it to RS232
  559. RSXIT:
  560.     pop dx
  561.     pop cx
  562.     pop bx
  563.     ret
  564. RS232_out endp
  565.  
  566.  
  567.  
  568. ; ----- CHDISP ----------------------------
  569. ; Display the character in AL on the CRT
  570. ; Entry:
  571. ;  AL = char
  572. ; Exit:
  573. ;  All regs restored
  574. ; -----------------------------------------
  575.  
  576. chdisp proc near
  577.     push ax
  578.     push dx
  579.     mov dl,al
  580.     @doscall 2
  581.     pop dx
  582.     pop ax
  583.     ret
  584. chdisp endp
  585.  
  586.  
  587.  
  588. ; ----- STRDISP ---------------------------
  589. ; Display the string at DS:DX on the CRT
  590. ; Entry:
  591. ;  DS:DX ==> string
  592. ; Exit:
  593. ;  All regs restored
  594. ; -----------------------------------------
  595.  
  596. strdisp proc near
  597.     push ax
  598.     @doscall 9
  599.     pop ax
  600.     ret
  601. strdisp endp
  602.  
  603.  
  604.  
  605. ; ----- INCPTR ----------------------------
  606. ; Increment the buffer pointer in reg BX.
  607. ; If the pointer goes beyond the end of the
  608. ; buffer, wrap around to start.
  609. ;
  610. ; Entry:
  611. ;  BX = buffer pointer
  612. ; Exit:
  613. ;  BX = advanced buffer pointer
  614. ;  Other regs restored
  615. ; -----------------------------------------
  616.  
  617. incptr proc near
  618.     inc bx                ; Bump pointer
  619.     cmp bx,offset bufend        ; Past end?
  620.     jne IP100            ; Jump if not
  621.     mov bx,offset buffer            ; Else point to start
  622. IP100:
  623.     ret
  624. incptr    endp
  625. code ends
  626.     end main
  627.